package com.ruoyi.framework.datasource.transaction;


import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.config.MyBatisConfig;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * com.ruoyi.framework.datasource.transaction
 *
 * @author jierui
 * @version v1.0
 * @date 2020/11/10
 * 描述：TODO
 */
@Configuration
public class DataSourceFactory {

    @Autowired
    private MyBatisConfig myBatisConfig;


    /**
     * sqlSessionTemplate 与 Spring 事务管理一起使用，以确保使用的实际 SqlSession 是与当前 Spring 事务关联的,
     * 此外它还管理会话生命周期，包括根据 Spring 事务配置根据需要关闭，提交或回滚会话
     *
     * @return
     */
    /*@Bean
    public CustomSqlSessionTemplate sqlSessionTemplate(DataSource dataSource) {
        Map<Object, SqlSessionFactory> sqlSessionFactoryMap = new HashMap<>();
        SqlSessionFactory sqlSessionFactory = null;

        try {
            sqlSessionFactory = myBatisConfig.createSqlSessionFactory(dataSource);
        } catch (Exception e) {
            e.printStackTrace();
        }
        sqlSessionFactoryMap.put(DataSourceType.MASTER.name(),sqlSessionFactory);
        CustomSqlSessionTemplate customSqlSessionTemplate = new CustomSqlSessionTemplate(sqlSessionFactory);
        customSqlSessionTemplate.setTargetSqlSessionFactories(sqlSessionFactoryMap);
        customSqlSessionTemplate.setDefaultTargetSqlSessionFactory(sqlSessionFactory);
        return customSqlSessionTemplate;
    }*/

    @Bean(name = "sqlSessionFactoryMaster")
    public SqlSessionFactory sqlSessionFactoryMaster(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
        return myBatisConfig.createSqlSessionFactory(dataSource);
    }

    //载yml中配置多数据源需要手动判断是否生效并初始化SqlSessionFactory
    @Bean(name = "sqlSessionFactorySlave")
    @ConditionalOnBean(name="slaveDataSource")
    public SqlSessionFactory sqlSessionFactorySlave(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
        return myBatisConfig.createSqlSessionFactory(dataSource);
    }

    @Bean(name = "sqlSessionTemplate")
    public CustomSqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryMaster") SqlSessionFactory factoryMaster,
                                                       RedisCache redisCache, Environment env) throws Exception {
        Map<Object, SqlSessionFactory> sqlSessionFactoryMap = new HashMap<>();
        sqlSessionFactoryMap.put(DataSourceType.MASTER.name(), factoryMaster);
        //载yml中配置多数据源需要手动判断是否生效并添加到sqlSessionTemplate和redisCache中
        if (SpringUtils.containsBean("slaveDataSource")) {
            sqlSessionFactoryMap.put(DataSourceType.SLAVE.name(), SpringUtils.getBean("sqlSessionFactorySlave"));
            //将数据源遍历放到redis中
            String pageKey = Constants.DATA_SOURCE_KEY + env.getProperty("spring.datasource.druid.slave.aopPackage");
            redisCache.getAndSetCacheObject(pageKey, DataSourceType.SLAVE.name());
        }

        CustomSqlSessionTemplate customSqlSessionTemplate = new CustomSqlSessionTemplate(factoryMaster);
        customSqlSessionTemplate.setTargetSqlSessionFactories(sqlSessionFactoryMap);
        return customSqlSessionTemplate;
    }
}
